/***************************************************************************
 *   Copyright (C) 2010 by Oleg Goncharov  *
 *   $EMAIL$                           *                          
 *                                                                         *
 *   This file is part of ChessVision.                                     *
 *                                                                         *
 *   ChessVision is free software; you can redistribute it and/or modify   *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include "cpointmatch.h"

CPointMatch::CPointMatch(IplImage * _sample, NormMode _mode) : CPointNorm(_mode) {
	sample = Normolize(_sample);
	therehold = sample->height*sample->width;
	therehold *= therehold;
}

CPointMatch::~CPointMatch() {
	cvReleaseImage(& sample);
}

bool CPointMatch::DetectPoint(IplImage* img, cv::Point2f& point) {
	IplImage * diff = cvCreateImage(cvSize(img->width-sample->width+1, img->height-sample->height+1), IPL_DEPTH_32F, 1);
	IplImage * src = Normolize(img);
	CvPoint min_loc;
	double min, max;
	
	cvMatchTemplate(src, sample, diff, CV_TM_SQDIFF);
	
	cvMinMaxLoc(diff, &min, &max, &min_loc, 0);
	point.x = min_loc.x + sample->width/2; point.y = min_loc.y + sample->height/2;
	
	cvReleaseImage(&diff);
	cvReleaseImage(&src);
	if (min <= therehold) return true;
	else return false;
}


CPointScaleMatch::CPointScaleMatch(IplImage * _sample, float min_scale, float max_scale, int nsteps, NormMode _mode) : CPointNorm(_mode) {
	float scale, sstep = fabs(min_scale - max_scale)/nsteps;
	int i;
	CvSize size;
	IplImage * sample = Normolize(_sample);
	therehold = sample->height*sample->width;
	therehold *= therehold;
	nsamples = nsteps + 1;
	
	samples = new IplImage*[nsamples];
	areas = new int[nsamples];
	
	//cvShowImage("win", sample); cvWaitKey(0);
	
	for(scale = min_scale, i = 0; i < nsamples; i++, scale +=  sstep) {
		size = cvSize(cvRound(scale*sample->width), cvRound(scale*sample->height));
		samples[i] = cvCreateImage(size, sample->depth, sample->nChannels);
		cvResize(sample, samples[i], CV_INTER_LINEAR);
		areas[i] = size.height*size.width;
	}
	
	cvReleaseImage(&sample);
}

bool CPointScaleMatch::DetectPoint(IplImage* img, cv::Point2f& point) {
	IplImage * diff = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, 1);
	IplImage * src = Normolize(img);
	CvPoint min_loc;
	double min, max, best = 1e100;
	
	//cvShowImage("win", src); cvWaitKey(0);

	for(int i = 0; i < nsamples; i++) {
		cvSetImageROI(diff, cvRect(0, 0, img->width-samples[i]->width+1, img->height-samples[i]->height+1));
		
		cvMatchTemplate(src, samples[i], diff, CV_TM_SQDIFF);
		cvMinMaxLoc(diff, &min, &max, &min_loc, 0);
		min /= areas[i];
		if (min < best) {
			best = min;
			point.x = min_loc.x + samples[i]->width/2; point.y = min_loc.y + samples[i]->height/2;
		}
	}

	cvReleaseImage(&diff);
	cvReleaseImage(&src);
	if (min <= therehold) return true;
	else return false;
}

CPointScaleMatch::~CPointScaleMatch() {
	for(int i = 0; i < nsamples; i++) cvReleaseImage(samples + i);
	delete [] samples;
	delete [] areas;
}

